
package com.lisn.fragmentationupload.upload;

import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.lisn.fragmentationupload.utils.MLog;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;

import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;

/**
 * 上传线程
 */
public class UploadTask implements Runnable {

    private static final String TAG = UploadTask.class.getSimpleName();

    private static String FILE_MODE = "rwd";
    private OkHttpClient mClient;
    private SQLiteDatabase db;
    private UploadTaskListener mListener;

    private Builder mBuilder;
    private String id;  // task id
    private String url; // file url
    private String filePath;
    private String fileName;
    private int uploadStatus;
    private int chunk, chunks; //流块

    private int errorCode;
    static String BOUNDARY = "----------" + System.currentTimeMillis();
    public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("multipart/form-data;boundary=" + BOUNDARY);

    private UploadTask(Builder builder) {
        mBuilder = builder;
        // extracted();

        this.id = mBuilder.id;
        this.url = mBuilder.url;
        this.filePath = mBuilder.filePath;
        this.fileName = mBuilder.fileName;
        this.uploadStatus = mBuilder.uploadStatus;
        this.chunk = mBuilder.chunk;
        this.setmListener(mBuilder.listener);
        // 以kb为计算单位
    }

    private void extracted() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                try {
                    if (message.length() > 500) {
                        Log.e("OKHttp-----", message);
                    } else {
                        String text = URLDecoder.decode(message, "utf-8");
                        Log.e("OKHttp-----", text);
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    Log.e("OKHttp-----", message);
                }
            }
        });
        //这行必须加 不然默认不打印
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        builder.addInterceptor(interceptor);
        mClient = builder.build();
    }

    @Override
    public void run() {
        try {
            int blockLength = 1024 * 1024;
            MLog.e(TAG, "run: filePath = " + filePath);
            File file = new File(filePath);
            MLog.e(TAG, "run: filePath = " + file.getAbsolutePath());
            if (file.length() % blockLength == 0) {
                chunks = (int) file.length() / blockLength;
            } else {
                chunks = (int) file.length() / blockLength + 1;
            }
            while (chunk <= chunks && uploadStatus != UploadStatus.UPLOAD_STATUS_PAUSE && uploadStatus != UploadStatus.UPLOAD_STATUS_ERROR) {

                uploadStatus = UploadStatus.UPLOAD_STATUS_UPLOADING;
                Map<String, String> params = new HashMap<String, String>();
                params.put("name", fileName);
                params.put("chunks", chunks + "");
                params.put("chunk", chunk + "");

                MLog.e(TAG, "run: name = " + fileName);
                MLog.e(TAG, "run: chunks = " + chunks);
                MLog.e(TAG, "run: chunck = " + chunk);

                final byte[] mBlock = FileUtils.getBlock((chunk - 1) * blockLength, file, blockLength);
                MLog.e(TAG, "run: mBlock " + mBlock.length);

                MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);

                // builder.addFormDataPart("name", fileName);
                // builder.addFormDataPart("chunks", chunks + "");
                // builder.addFormDataPart("chunk", chunk + "");
                addParams(builder, params);

                RequestBody requestBody = RequestBody.create(MEDIA_TYPE_MARKDOWN, mBlock);
                builder.addFormDataPart("mFile", fileName, requestBody);

                Request request = new Request.Builder()
                        .url(url)
                        .post(builder.build())
                        .build();
                Response response = mClient.newCall(request).execute();
                if (response.isSuccessful()) {
                    MLog.e(TAG, "run: isSuccessful");
                    onCallBack();
                    chunk++;

                } else {
                    uploadStatus = UploadStatus.UPLOAD_STATUS_ERROR;
                    errorCode = 1001;
                    onCallBack();
                    MLog.e(TAG, "run: no isSuccessful");
                }
            }

            if (chunk >= chunks) {
                uploadStatus = UploadStatus.UPLOAD_STATUS_COMPLETED;
                onCallBack();
            }
        } catch (IOException e) {
            uploadStatus = UploadStatus.UPLOAD_STATUS_ERROR;
            errorCode = 1002;
            onCallBack();
            e.printStackTrace();
            MLog.e(TAG, "run: " + e);
        }
    }


    /**
     * 分发回调事件到ui层
     */
    private void onCallBack() {
        mHandler.sendEmptyMessage(uploadStatus);
        // 同步manager中的task信息
        //UploadManager.getInstance().updateUploadTask(this);
    }

    Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            int code = msg.what;
            switch (code) {
                // 上传失败
                case UploadStatus.UPLOAD_STATUS_ERROR:
                    mListener.onError(UploadTask.this, errorCode);
                    break;
                // 正在上传
                case UploadStatus.UPLOAD_STATUS_UPLOADING:
                    mListener.onUploading(UploadTask.this, getDownLoadPercent());
                    break;
                // 暂停上传
                case UploadStatus.UPLOAD_STATUS_PAUSE:
                    mListener.onPause(UploadTask.this);
                    break;
                // 暂停上传
                case UploadStatus.UPLOAD_STATUS_COMPLETED:
                    mListener.onUploadSuccess(UploadTask.this, filePath);
                    break;
            }
        }
    };

    private String getDownLoadPercent() {
        String baifenbi = "0";// 接受百分比的值
        if (chunk >= chunks) {
            return "100";
        }
        double baiy = chunk * 1.0;
        double baiz = chunks * 1.0;
        // 防止分母为0出现NoN
        if (baiz > 0) {
            double fen = (baiy / baiz) * 100;
            //NumberFormat nf = NumberFormat.getPercentInstance();
            //nf.setMinimumFractionDigits(2); //保留到小数点后几位
            // 百分比格式，后面不足2位的用0补齐
            //baifenbi = nf.format(fen);
            //注释掉的也是一种方法
            DecimalFormat df1 = new DecimalFormat("0");//0.00
            baifenbi = df1.format(fen);
        }
        MLog.e(TAG, "getDownLoadPercent: baifenbi = " + baifenbi);
        return baifenbi;
    }


    private String getFileNameFromUrl(String url) {
        if (!TextUtils.isEmpty(url)) {
            return url.substring(url.lastIndexOf("/") + 1);
        }
        return System.currentTimeMillis() + "";
    }

    private void close(Closeable closeable) {
        try {
            closeable.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setClient(OkHttpClient mClient) {
        this.mClient = mClient;
    }

    public Builder getBuilder() {
        return mBuilder;
    }

    public void setBuilder(Builder builder) {
        this.mBuilder = builder;
    }

    public String getId() {
        if (!TextUtils.isEmpty(id)) {
        } else {
            id = url;
        }
        return id;
    }

    public String getUrl() {
        return url;
    }

    public String getFilePath() {
        return filePath;
    }

    public String getFileName() {
        return fileName;
    }


    public void setUploadStatus(int uploadStatus) {
        this.uploadStatus = uploadStatus;
    }

    public int getUploadStatus() {
        return uploadStatus;
    }


    public void setmListener(UploadTaskListener mListener) {
        this.mListener = mListener;
    }

    public static class Builder {
        private String id; // task id
        private String url; // file url
        private String fileName; // File name when saving
        private String filePath; // File path
        private int uploadStatus = UploadStatus.UPLOAD_STATUS_INIT;
        private int chunk;//第几块
        private UploadTaskListener listener;

        /**
         * 作为上传task开始、删除、停止的key值，如果为空则默认是url
         *
         * @param id
         * @return
         */
        public Builder setId(String id) {
            this.id = id;
            return this;
        }

        /**
         * 上传url（not null）
         *
         * @param url
         * @return
         */
        public Builder setUrl(String url) {
            this.url = url;
            return this;
        }

        /**
         * 设置上传状态
         *
         * @param uploadStatus
         * @return
         */
        public Builder setUploadStatus(int uploadStatus) {
            this.uploadStatus = uploadStatus;
            return this;
        }

        /**
         * 第几块
         *
         * @param chunk
         * @return
         */
        public Builder setChunk(int chunk) {
            this.chunk = chunk;
            return this;
        }


        /**
         * 设置文件名
         *
         * @param fileName
         * @return
         */
        public Builder setFileName(String fileName) {
            this.fileName = fileName;
            return this;
        }

        /**
         * 文件路径
         *
         * @param filePath
         * @return
         */
        public Builder setFilePath(String filePath) {
            this.filePath = filePath;
            return this;
        }

        /**
         * 设置上传回调
         *
         * @param listener
         * @return
         */
        public Builder setListener(UploadTaskListener listener) {
            this.listener = listener;
            return this;
        }

        public UploadTask build() {
            return new UploadTask(this);
        }
    }

    private void addParams(MultipartBody.Builder builder, Map<String, String> params) {
        if (params != null && !params.isEmpty()) {
            for (String key : params.keySet()) {
                builder.addPart(Headers.of("Content-Disposition",
                        "form-data; name=\"" + key + "\""),
                        RequestBody.create(null, params.get(key)));
            }
        }
    }
}
